package server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;

public class ChatServer extends Thread {
    private final List<Socket> clients = new LinkedList<>();
    private final ReadWriteLock lock = new ReadWriteLock();

    @Override public void run() {
        try(ServerSocket ss = new ServerSocket(9999)) {
            while(true) {
                final Socket clientSocket = ss.accept();
                lock.setRead();
                clients.add(clientSocket);
                lock.resetRead();

                new Thread() {
                    @Override public void run() {
                        while(true) {
                            try {
                                final String message = ">>" + new DataInputStream(clientSocket.getInputStream()).readUTF();

                                new Thread() {
                                    @Override public void run() {
                                        lock.setWrite();
                                        for(Socket client : clients) {
                                            try {
                                                new DataOutputStream(client.getOutputStream()).writeUTF(message);
                                            } catch (IOException e) {}
                                        }
                                        lock.resetWrite();
                                    }
                                }.start();
                            } catch (IOException e) {}
                        }
                    }
                }.start();
            }
        } catch(IOException e) {
            System.out.println("Server stopped");
        }
    }
}

class ReadWriteLock {
    private static int writersCount;
    private Boolean isRead;

    public synchronized void setRead() {
        isRead = true;
        while(writersCount > 0) {}
    }

    public synchronized void setWrite() {
        while(isRead) {}
        writersCount++;
    }

    public synchronized void resetRead() {
        isRead = false;
    }

    public synchronized void resetWrite() {
        writersCount--;
    }

}